import { TOKEN_STORAGE, TOKEN_HEADER } from "@/types/constant";
import { Result } from "@/types/common";

/**
 * 请求方式枚举
 */
export const method = {
  get: "GET",
  post: "POST",
};

/**
 * 全局请求方法
 * @param url 请求地址
 * @param options 请求参数
 * @returns JSON响应
 */
export const request = async (
  url: string,
  options?: RequestInit
): Promise<Result<any>> => {
  if (options) {
    const headers = new Headers(options.headers);
    headers.append(TOKEN_HEADER, localStorage.getItem(TOKEN_STORAGE) || "");
    options.headers = headers;
  } else {
    const headers = new Headers();
    headers.append(TOKEN_HEADER, localStorage.getItem(TOKEN_STORAGE) || "");
    options = {
      headers,
    };
  }
  try {
    const response = await fetch(import.meta.env.VITE_BASE_API + url, options);
    const data = response.json();
    if (response.ok) {
      return data;
    }
  } catch (error) {
    console.log(error);
  }
  throw new Error("网络错误");
};

/**
 * GET请求
 * @param url 请求地址
 * @param param 参数对象
 * @returns JSON响应
 */
export const get = async (
  url: string,
  param?: any,
  options?: RequestInit
): Promise<Result<any>> => {
  if (param) {
    let paramsArray: string[] = [];
    //拼接参数
    Object.keys(param).forEach((key) =>
      paramsArray.push(key + "=" + param[key])
    );
    if (url.search(/\?/) === -1) {
      url += "?" + paramsArray.join("&");
    } else {
      url += "&" + paramsArray.join("&");
    }
  }
  return await request(url, {
    ...(options || {}),
    method: method.get,
  });
};

/**
 * POST请求
 * @param url 请求地址
 * @param param 参数对象
 * @returns JSON响应
 */
export const post = async (
  url: string,
  param?: any,
  options?: RequestInit
): Promise<Result<any>> => {
  if (options) {
    const headers = new Headers(options.headers);
    headers.append("Content-Type", "application/json");
    options.headers = headers;
  } else {
    const headers = new Headers();
    headers.append("Content-Type", "application/json");
    options = {
      headers,
    };
  }
  return await request(url, {
    ...options,
    method: method.post,
    body: param ? JSON.stringify(param) : null,
  });
};

/**
 * 下载文件
 * @param url 文件地址
 * @param filename 文件名称
 * @returns void || json
 */
export const download = async (
  url: string,
  filename: string = "下载文件"
): Promise<Result<any>> => {
  // 设置请求头
  const headers = new Headers();
  headers.append(TOKEN_HEADER, localStorage.getItem(TOKEN_STORAGE) || "");

  // 发送请求
  const response = await fetch(import.meta.env.VITE_BASE_API + url, {
    headers,
  });

  // 检查响应类型是否为 JSON
  const contentType = response.headers.get("content-type");
  if (contentType && contentType.includes("application/json")) {
    const json = await response.json();
    return json;
  }

  // 取响应头中文件名字
  let originalFilename;
  const contentDisposition = response.headers.get("Content-Disposition");
  if (contentDisposition) {
    const match = contentDisposition.split("filename=")
    if (match) {
      originalFilename = match[1];
    }
  }

  // 二进制数据创建资源路径，创建<a>标签点击下载
  // 注意blob数据过大时有可能吃满内存
  const blob = await response.blob();
  const tempUrl = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = tempUrl;
  a.download = originalFilename || filename;
  document.body.appendChild(a);
  a.click();
  URL.revokeObjectURL(tempUrl);
  document.body.removeChild(a);

  // 手动返回一个成功状态
  return {
    code: 200,
    message: "下载成功",
    data: null,
  };
};
